#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>


#include <string.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>


#include "generclient.h"
#define   ADRESS(x)                     "#x"


struct GenericClient_t
{
    IOfunc                    m_session;
    prot_e                    m_prot;
    int                       m_clientSockfd;
    struct sockaddr_in        m_clientAddr;
};

/**************************InternalFunctions Declaration*******************************************************/

static int SocketNew(int* _socket,struct sockaddr_in* _saddr,
                    const char* _name,char* _ClientIP,int _serverPort,int _protocol);

/********************API**************Fucntion********************************************************/

Gcl* GclNewClient(int _protocol,IOfunc _session,int _serverPort,char* _ClientIP)
{
    Gcl*    gcl = malloc(sizeof(Gcl));

    gcl->m_session       = _session;
    gcl->m_prot          = _protocol;


    if(SocketNew(&gcl->m_clientSockfd,&gcl->m_clientAddr,0,_ClientIP, _serverPort, _protocol) )
    {
        fprintf(stderr,"\nSocket New problems\n");
        free(gcl);
        return 0;
    }
    return gcl;
}

int GclConnectClient(Gcl* _gcl)
{
    int err=0;
    err = connect(_gcl->m_clientSockfd,(struct sockaddr*)&_gcl->m_clientAddr,sizeof(struct sockaddr_in));
    if(err == -1)
    {
        perror("connect");
        fflush(stdout);

    }
    return err;
}


int GclRunClient(Gcl* _gcl)
{
    int       wr;
    wr=_gcl->m_session(_gcl->m_clientSockfd,&_gcl->m_clientAddr);
    if(wr == -1 && errno == EPIPE)
    {
        fprintf(stderr, " Problems with connection, line : %d ", __LINE__);
    }

  close(_gcl->m_clientSockfd);
  printf("\nClient  finished\n");
  return 0;
}

/**************************** Internal function Implementation*************************************************/
static int SocketNew(int* _socket,struct sockaddr_in* _saddr,
                    const char* _name,char* _ClientIP,int _serverPort,int _protocol)
{

    if (_protocol == TCP)
    {
        *_socket = socket( AF_INET /*1st argument is the purpose AF_UNIX local*/ ,
                SOCK_STREAM /*communication sematics SOCK_STREAM ==two way connect*/,
                0/*Protocol*/);
    }



    if (_protocol == UDP)
    {
         *_socket = socket( AF_INET /*1st argument is the purpose AF_UNIX local*/ ,
               SOCK_DGRAM  /*communication UDP connection*/,
                0/*Protocol*/);
    }

    if(*_socket ==-1)
    {
        perror("socket");
        return 1;
    }
    _saddr->sin_family = AF_INET;/*dueto AF_UNIX unix(7) instructions*/
    _saddr->sin_addr.s_addr = inet_addr(_ClientIP);/*dueto AF_UNIX unix(7) instructions)*/
   _saddr->sin_port = htons(_serverPort);/*convert byte representation on number to network represent*/
    return 0;

}

